import json
import  datetime
from django.shortcuts import redirect, render, HttpResponse, reverse
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.utils.safestring import mark_safe

from web.forms.issues import IssuesModelForm, IssuesReplyModelForm, InviteModelForm
from web import models
from utils.pagination import Pagination
from utils.encrypt import uid


class SelectFilter(object):
    def __init__(self, data_list, request, name):
        self.data_list = data_list
        self.request = request
        self.name = name

    def __iter__(self):
        yield mark_safe("<select class='select2' multiple='multiple' style='width:100%;' >")
        for item in self.data_list:
            key = str(item[0])
            text = item[1]

            value_list = self.request.GET.getlist(self.name)
            selected = ""
            if key in value_list:
                # 前端发来的查询条件在data_list中，默认选中
                selected = "selected"
                value_list.remove(key)
            else:
                value_list.append(key)

            query_dict = self.request.GET.copy()
            query_dict._mutable = True
            query_dict.setlist(self.name, value_list)
            if 'page' in query_dict:
                query_dict.pop('page')

            param_url = query_dict.urlencode()
            if param_url:
                url = "{}?{}".format(self.request.path_info, param_url)  # status=1&status=2&status=3&xx=1
            else:
                url = self.request.path_info

            html = "<option value='{url}' {selected} >{text}</option>".format(url=url, selected=selected, text=text)
            yield mark_safe(html)

        yield mark_safe("</select>")


class CheckFilter(object):
    def __init__(self, data_list, request, name):
        self.data_list = data_list
        self.request = request
        self.name = name

    def __iter__(self):
        # data_list: (1, '新建')
        for item in self.data_list:
            key = str(item[0])
            text = item[1]
            # 从前端url中获取查询字符串
            value_list = self.request.GET.getlist(self.name)
            ck = ""
            if key in value_list:
                # 前端发来的查询条件在data_list中，默认选中
                ck = "checked"
                value_list.remove(key)
            else:
                value_list.append(key)

            # 为前端checkbox生成url
            query_dict = self.request.GET.copy()
            # 可以改动request.GET的内容
            query_dict._mutable = True
            query_dict.setlist(self.name, value_list)
            # 筛选后把分页去掉，改成第一页
            if 'page' in query_dict:
                query_dict.pop('page')

            # 取消checkbox后，去掉url中的 ?
            # query_dict.urlencode() 可以把 {"status":[1,2,3], "xx": 1}  解析成 status=1&status=2&status=3&xx=1
            # 为前端的筛选框中的checkbox绑定url,点击可以自动筛选
            param_url = query_dict.urlencode()
            if param_url:
                url = "{}?{}".format(self.request.path_info, param_url)
            else:
                url = self.request.path_info

            tpl = '<a class="cell" href="{url}"><input type="checkbox" {ck} /><label>{text}</label></a>'
            html = tpl.format(ck=ck, text=text, url=url)
            yield mark_safe(html)


def issues(request, project_id):
    """添加问题、查看问题列表"""
    if request.method == 'GET':
        # 根据URL做筛选过滤要展示的问题
        filter_allow_type = ["priority", "status", "issues_type", "assign", "attention"]  # 允许筛选的字段
        # 筛选条件的字典
        condition_dict = {}
        for item in filter_allow_type:
            filter_list = request.GET.getlist(item)
            if not filter_list:
                # 没有传筛选值
                continue
            # 构造筛选条件的字典
            condition_dict["{}__in".format(item)] = filter_list
            """
            condition_dict = {
                "priority__in": [1,2]
                "status": [1,2]
            }
            """

        # 查看问题列表
        form = IssuesModelForm(request)
        query_set = models.Issues.objects.filter(project_id=project_id).filter(**condition_dict)  # 根据筛选条件查找问题

        # 分页
        page_object = Pagination(
            current_page=request.GET.get("page"),
            all_count=query_set.count(),
            base_url=request.path_info,
            query_params=request.GET,
            per_page=50
        )

        issues_object_list = query_set[page_object.start: page_object.end]

        project_issues_type = models.IssuesType.objects.filter(project_id=project_id).values_list('id', 'title')

        # 当前项目的创建者和所有的参与者
        total_user_list = [(request.tracer.project.creator_id, request.tracer.project.creator.username)]
        # 参与者
        join_user_list = models.ProjectUser.objects.filter(project_id=project_id).values_list("user_id",
                                                                                              "user__username")

        total_user_list.extend(join_user_list)

        # 邀请码
        invite_form = InviteModelForm()

        context = {
            "form": form,
            "invite_form": invite_form,
            "issues_object_list": issues_object_list,
            "page_object": page_object,
            # 迭代器，给前端返回迭代的标签
            "filter_list": [
                {"title": "状态", "filter": CheckFilter(models.Issues.status_choices, request, "status")},
                {"title": "优先级", "filter": CheckFilter(models.Issues.priority_choices, request, "priority")},
                {"title": "问题类型", "filter": CheckFilter(project_issues_type, request, "issues_type")},
                {"title": "指派者", "filter": SelectFilter(total_user_list, request, "assign")},
                {"title": "关注者", "filter": SelectFilter(total_user_list, request, "attention")},
            ],
        }
        """
            models.Issues.status_choices
            status_choices = (
            (1, '新建'),
            (2, '处理中'),
            (3, '已解决'),
            (4, '已忽略'),
            (5, '待反馈'),
            (6, '已关闭'),
            (7, '重新打开'),
        )
        """
        return render(request, "issues.html", context)

    form = IssuesModelForm(request, data=request.POST)
    if form.is_valid():
        # 添加问题
        form.instance.project = request.tracer.project
        form.instance.creator = request.tracer.user
        form.save()

        return JsonResponse({"status": True})

    return JsonResponse({"status": False, "error": form.errors})


def issues_detail(request, project_id, issues_id):
    """编辑问题页面"""
    issues_object = models.Issues.objects.filter(id=issues_id, project_id=project_id).first()
    form = IssuesModelForm(request, instance=issues_object)
    return render(request, "issues_detail.html", {"form": form, "issues_object": issues_object})


@csrf_exempt
def issues_record(request, project_id, issues_id):
    """操作记录展示"""
    if request.method == "GET":
        issues_reply_object_list = models.IssuesReply.objects.filter(issues_id=issues_id,
                                                                     issues__project=request.tracer.project)
        data_issues_reply_list = []
        for item in issues_reply_object_list:
            data_dict = {
                "id": item.id,
                "reply_type_text": item.get_reply_type_display(),
                "content": item.content,
                "creator": item.creator.username,
                "datetime": item.create_datetime.strftime('%Y-%m-%d %H-%M'),
                "parent_id": item.reply_id,
            }
            data_issues_reply_list.append(data_dict)

        return JsonResponse({"status": True, "data": data_issues_reply_list})

    form = IssuesReplyModelForm(data=request.POST)
    if form.is_valid():
        form.instance.creator = request.tracer.user
        form.instance.reply_type = 2
        form.instance.issues_id = issues_id
        instance = form.save()

        info = {
            "id": instance.id,
            "reply_type_text": instance.get_reply_type_display(),
            "content": instance.content,
            "creator": instance.creator.username,
            "datetime": instance.create_datetime.strftime('%Y-%m-%d %H-%M'),
            "parent_id": instance.reply_id,
        }

        return JsonResponse({"status": True, "data": info})

    return JsonResponse({"status": False, "error": form.errors})


@csrf_exempt
def issues_change(request, project_id, issues_id):
    """初始化操作记录"""
    issues_object = models.Issues.objects.filter(id=issues_id, project=request.tracer.project).first()
    issues_dict = json.loads(request.body.decode("utf-8"))
    # print(issues_dict)  # {'name': 'issues_type', 'value': '2'}

    name = issues_dict.get("name")
    value = issues_dict.get("value")

    def create_reply_dict(content):
        # 生成一个issue_type对象
        new_issue_type_object = models.IssuesReply.objects.create(
            reply_type=1,
            issues=issues_object,
            content=change_record,
            creator=request.tracer.user,
        )

        # 在操作记录列表中展示此次的操作记录
        data = {
            "id": new_issue_type_object.id,
            "reply_type_text": new_issue_type_object.get_reply_type_display(),
            "content": new_issue_type_object.content,
            "creator": new_issue_type_object.creator.username,
            "datetime": new_issue_type_object.create_datetime.strftime('%Y-%m-%d %H-%M'),
            "parent_id": new_issue_type_object.reply_id,
        }

        return data

    # 字符串形式获取orm字段
    field_object = models.Issues._meta.get_field(name)
    # 问题变更：文本信息
    if name in ["subject", "desc", "start_date", "end_date"]:
        if not value:
            # name未传值
            if not field_object.null:
                # 数据库中此字段不能为空
                return JsonResponse({"status": False, "error": "此项不能为空"})

            # 数据库中此字段可以为空
            setattr(issues_object, name, None)
            issues_object.save()
            change_record = "{}更新为空".format(field_object.verbose_name)
        else:
            # name传的有值
            setattr(issues_object, name, value)
            issues_object.save()
            change_record = "{}更新为{}".format(field_object.verbose_name, value)

        return JsonResponse({"status": True, "data": create_reply_dict(change_record)})

    # 问题变更：pk值
    if name in ["issues_type", "assign", "module", "parent"]:
        if not value:
            # name未传值，为空
            if not field_object.null:
                # 此字段不允许为空
                return JsonResponse({"status": False, "error": "此项不能为空"})

            # 此字段可以为空
            setattr(issues_object, name, None)
            issues_object.save()
            change_record = "{}更新为空".format(field_object.verbose_name)
        else:
            # name传值了
            # name传的有值
            if name == 'assign':
                # 是否是项目创建者
                if value == str(request.tracer.project.creator_id):
                    instance = request.tracer.project.creator
                else:
                    project_user_object = models.ProjectUser.objects.filter(project_id=project_id,
                                                                            user_id=value).first()
                    if project_user_object:
                        instance = project_user_object.user
                    else:
                        instance = None
                if not instance:
                    return JsonResponse({'status': False, 'error': "您选择的值不存在"})

                setattr(issues_object, name, instance)
                issues_object.save()
                change_record = "{}更新为{}".format(field_object.verbose_name, str(instance))  # value根据文本获取到内容
            else:
                # 条件判断：用户输入的值，是自己的值。
                instance = field_object.rel.model.objects.filter(id=value, project_id=project_id).first()
                if not instance:
                    return JsonResponse({'status': False, 'error': "您选择的值不存在"})

                setattr(issues_object, name, instance)
                issues_object.save()
                change_record = "{}更新为{}".format(field_object.verbose_name, str(instance))

        return JsonResponse({"status": True, "data": create_reply_dict(change_record)})

    # 问题变更：choices
    if name in ["priority", "status", "mode"]:
        select_text = None
        for key, text in field_object.choices:
            # 看传过来的choices的值是否再数据库中对应的choices中
            if str(key) == value:
                select_text = text

        if not select_text:
            # 传过来的值不存在
            return JsonResponse({"status": False, "error": "您选择的值不存在"})

        setattr(issues_object, name, value)
        issues_object.save()
        change_record = "{}更新为{}".format(field_object.verbose_name, select_text)

        return JsonResponse({"status": True, "data": create_reply_dict(change_record)})

    # 问题变更：多对多字段
    if name == "attention":
        # value = [关注者id]
        # 先判断是否是列表类型
        if not isinstance(value, list):
            return JsonResponse({"status": False, "error": "数据格式错误"})

        # value列表是否为空
        if not value:
            # 数据库中关注者字段设置为空
            issues_object.attention.set(value)
            issues_object.save()
            change_record = "{}更新为空".format(field_object.verbose_name)
        else:
            # 从数据库中获取当前项目的创建者和所有参与者
            project_user_list = models.ProjectUser.objects.filter(project_id=project_id)
            user_dict = {str(request.tracer.project.creator_id): request.tracer.project.creator.username}

            # 构建当前项目的创建者和所有参与者的字典 {id:name}
            for item in project_user_list:
                user_dict[str(item.user_id)] = item.user.username

            # 校验通过的关注者列表
            username_list = []

            # 遍历value，判断前端传过来的关注者id是否再前项目的创建者和所有参与者的字典里
            for user_id in value:
                username = user_dict.get(str(user_id))
                if not username:
                    # 只要有一个不在，就返回错误提示，不再往下执行
                    return JsonResponse({"status": False, "error": "用户不存在，请重新设置"})
                username_list.append(username)

            # 多对多设置外键字段更新
            issues_object.attention.set(value)
            issues_object.save()
            change_record = "{}更新为{}".format(field_object.verbose_name, ",".join(username_list))

        return JsonResponse({"status": True, "data": create_reply_dict(change_record)})

    return JsonResponse({"status": False, "error": "滚蛋"})


def invite_url(request, project_id):
    """生成邀请码"""
    form = InviteModelForm(data=request.POST)
    if form.is_valid():
        # 非项目创建者不能邀请
        if request.tracer.user != request.tracer.project.creator:
            form.add_error("period", "无权创建邀请码")
            return JsonResponse({"status": False, "error": form.errors})

        # 将邀请记录保存在数据库中
        random_invite_code = uid(request.tracer.user.mobile_phone)
        form.instance.code = random_invite_code
        form.instance.creator = request.tracer.user
        form.instance.project = request.tracer.project
        form.instance.save()

        url_path = reverse("invite_join", kwargs={"code": random_invite_code})
        # 生成邀请链接
        url = "{scheme}://{host}{path}".format(
            scheme=request.scheme,
            host=request.get_host(),
            path=url_path
        )

        return JsonResponse({"status": True, "data": url})

    return JsonResponse({"status": False, "error": "生成邀请码失败"})


def invite_join(request, code):
    """访问邀请码"""
    current_datetime = datetime.datetime.now()
    # 邀请码不存在
    invite_object = models.ProjectInvite.objects.filter(code=code).first()
    if not invite_object:
        return render(request, "invite_join.html", {"error": "邀请码不存在"})

    # 项目的创建者不能加入项目
    if invite_object.creator == request.tracer.user:
        return render(request, "invite_join.html", {"error": "项目创建者不能再加入项目"})

    # 当前用户是否已加入项目
    exist = models.ProjectUser.objects.filter(project=invite_object.project, user=request.tracer.user).exists()
    if exist:
        return render(request, "invite_join.html", {"error": "您已加入此项目，无需再次加入"})

    # 邀请的成员数量是否大于此套餐的成员数量
    # ####### 问题1： 最多允许的成员(要进入的项目的创建者的限制）#######
    # max_member = request.tracer.price_policy.project_member # 当前登录用户他限制

    # 是否已过期，如果已过期则使用免费额度
    max_transaction = models.Transaction.objects.filter(user=invite_object.project.creator).order_by('-id').first()
    if max_transaction.price_policy.category == 1:
        max_member = max_transaction.price_policy.project_member
    else:
        if max_transaction.end_datetime < current_datetime:
            free_object = models.PricePolicy.objects.filter(category=1).first()
            max_member = free_object.project_member
        else:
            max_member = max_transaction.price_policy.project_member

    # 邀请码是否过期
    limit_datetime = invite_object.create_datetime + datetime.timedelta(minutes=invite_object.period)
    if limit_datetime < current_datetime:
        return render(request, "invite_join.html", {"error": "邀请码已过期"})

    # 邀请数量是否超过开始确认的邀请数量
    if invite_object.count:
        # 有值，就是有数量限制
        if invite_object.use_count >= invite_object.count:
            return render(request, "invite_join.html", {"error": "邀请数量已使用完"})

        invite_object.use_count += 1
        invite_object.save()

    # 添加邀请的用户到项目中
    models.ProjectUser.objects.create(user=request.tracer.user, project=invite_object.project)

    # ####### 问题2： 更新项目参与成员 #######
    invite_object.project.join_count += 1
    invite_object.project.save()

    return render(request, "invite_join.html", {"project": invite_object.project})

